﻿#include "pch.h"
#include "device_ctrl.h"

#pragma warning(push)
#pragma warning(disable : 4244)
#pragma warning(disable : 26451)

#define LOG_TAG		"设备控制"
#define LOG_LVL		LOG_LVL_DBG
#include "spk_ulog.h"


device_ctrl::device_ctrl()
{
	fd         = -1;
	fd_c       = -1;
	notify_win = nullptr;
	thread     = nullptr;
}

device_ctrl::~device_ctrl()
{
	if (fd >= 0)   closesocket(fd);
	if (fd_c >= 0) closesocket(fd_c);
	fd            = -1;
	fd_c          = -1;
	notify_win    = nullptr;
}

int device_ctrl::run(string server_ip, int port)
{
	if(fd >= 0) return fd;

	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));

	addr.sin_family      = AF_INET;
	addr.sin_addr.s_addr = (server_ip == "") ? INADDR_ANY : inet_addr(server_ip.c_str());
	addr.sin_port        = htons(port);

	/*创建socket*/
	fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (fd < 0)
	{
		LOG_E("tcp socket创建失败!");
		return -1;
	}

	/*本机作为服务器*/
	if(server_ip == "")
	{
		REUSE_PORT(fd)
		/*绑定到指定端口*/
		int err = ::bind(fd, (struct sockaddr*)&addr, sizeof(addr));

		if (err < 0)
		{
			LOG_E("tcp socket绑定失败!");
			closesocket(fd);
			return -1;
		}

		/*监听客户端请求*/
		err = listen(fd, 1);

		if (err < 0)
		{
			LOG_E("socket监听失败!");
			closesocket(fd);
			return -1;
		}
		fd_c = 0; 
	}
	/*本机作为客户端*/
	else
	{
		/*尝试连接服务器(设备端TCP端口)*/
		if (::connect(fd, (sockaddr*)&addr, sizeof(addr)) < 0)
		{
			LOG_E("连接设备(%s:%d)失败!", server_ip.c_str(), port);
			return -1;
		}
		fd_c = -1; 
	}

	/*后台接收客户端连接请求*/
	/*同时在此线程接收控制指令，因此此应用不支持多个设备同时连接配置*/
	thread = new std::thread(device_ctrl::recv_packet_thread, this);
	//recv_packet_thread(this);
	return fd;
}


void device_ctrl::on_rx_packet(void* rx_buffer, int len, u8 type, void* param)
{
	device_ctrl* ins = (device_ctrl*)param;

	switch(type)
	{
		case CMD_DEVICE_CTRL:        ins->ctrl(rx_buffer);               break;
		case CMD_DEVICE_REFRESH:     ins->refresh();                     break;
		case CMD_DEVICE_REBOOT:      ins->reboot();                      break;
		case CMD_DEVICE_CTRL_ACK:    ins->on_ctrl_ack(rx_buffer,len);	 break;
		case CMD_DEVICE_REFRESH_ACK: ins->on_refresh_ack(rx_buffer,len); break;
		case CMD_DEVICE_REBOOT_ACK:  ins->on_reboot_ack(rx_buffer,len);	 break;
		default: break; 
	}
}

int device_ctrl::io_read(void* data, int len, int time_out_ms, void* param)
{
	device_ctrl *ins = (device_ctrl*)param;
	int _fd = ins->fd_c > 0 ? ins->fd_c : ins->fd;
	int st = recv(_fd,(char*)data, len, 0);
	return st;
}

int device_ctrl::io_write(void* data, int len, void* param)
{
	device_ctrl *ins = (device_ctrl*)param;
	int _fd = ins->fd_c > 0 ? ins->fd_c : ins->fd;
	int st = send(_fd, (const char*)data, len, 0);
	return st;
}

void device_ctrl::recv_packet_thread(void* arg)
{
	device_ctrl *ins = (device_ctrl*)arg;

	if(ins->fd_c == 0)
	{
		struct sockaddr_in client_addr;
		socklen_t sock_len = sizeof(client_addr);

		while (1)
		{
			/*接收客户端连接请求*/
			ins->fd_c = ::accept(ins->fd, (struct sockaddr*)&client_addr, &sock_len);

			if (ins->fd_c < 0)
			{
				LOG_E("控制端口socket accept失败!");
				::closesocket(ins->fd);
				ins->fd = -1;
				return;
			}

			LOG_D("accept client(%u.%u.%u.%u)",client_addr.sin_addr.s_addr & 0xFF,(client_addr.sin_addr.s_addr>>8) & 0xFF,(client_addr.sin_addr.s_addr>>16) & 0xFF,(client_addr.sin_addr.s_addr>>24) & 0xFF);
			
			/*接收客户端指令*/
			spk_packet::recv_packet_thread_ex(ins->io_read, ins->on_rx_packet,ins); 
		}
	}
	else
	{
		/*接收服务器端指令*/
		spk_packet::recv_packet_thread_ex(ins->io_read, ins->on_rx_packet,ins); 
	}
}

int device_ctrl::get_device_info(struct device_info* msg)
{
	int st = 0;
#ifdef _WIN32
#else 
	st = init_file_decode("config.ini", msg);
	/*这里需要加入DHCP/IP/DNS等查询功能*/
#endif
	return st;
}

int device_ctrl::set_device_info(struct device_info* msg)
{
	int st = 0;
#ifdef _WIN32
#else 
	st = init_file_encode("config.ini", msg);
	/*这里需要加入DHCP/IP/DNS等设置功能*/
#endif
	return st;
}

int device_ctrl::on_ctrl_ack(void *dat,int len)
{
	int st = 0;
#ifdef _WIN32
	if(len == 4)
	{
	}
	else
	{
		AfxMessageBox("设备配置成功!", MB_ICONINFORMATION);
	}	
#else 
#endif 
	return st;
}

int device_ctrl::on_reboot_ack(void *dat,int len)
{
	int st = 0;
#ifdef _WIN32 
	if(len == 4)
	{
	}
	else
	{
		AfxMessageBox("设备重启成功!", MB_ICONINFORMATION);
	}	
#else 
#endif 
	return st;
}

int device_ctrl::on_refresh_ack(void *dat,int len)
{
	int st = 0;
#ifdef _WIN32 
	if(len == 4)
	{
	}
	else
	{
		int cmd = CMD_DEVICE_REFRESH_ACK;
		::SendMessage(notify_win, MSG_DEVICE_CTRL, (WPARAM)dat, (LPARAM)&cmd);
	}
#else 
#endif
	return st;
}

int device_ctrl::reboot(void)
{
#ifdef _WIN32 
	return send_packet(CMD_DEVICE_REBOOT,nullptr,0,this);
#else 
	/*获得当前配置*/
	int st  = 0;
	/*这里加入设备复位指令*/
	send_packet(CMD_DEVICE_REBOOT_ACK,&st,4,this);
	return st;
#endif 
}


int device_ctrl::refresh(void)
{
#ifdef _WIN32 
	return send_packet(CMD_DEVICE_REFRESH,nullptr,0,this);
#else 
	/*获得当前配置*/
	struct device_info msg;
	int st  = get_device_info(&msg);
	/*设置结果发送到PC*/
	if(st == SPK_ERR_NONE)
	{
		send_packet(CMD_DEVICE_REFRESH_ACK,&msg,sizeof(msg),this);
	}
	else
	{
		send_packet(CMD_DEVICE_REFRESH_ACK,&st,4,this);
	}

	return st;
#endif 
}

int device_ctrl::ctrl(void *data)
{
	struct device_info msg;
	memcpy(&msg,data,sizeof(struct device_info));

#ifdef _WIN32 
	return send_packet(CMD_DEVICE_CTRL,&msg,sizeof(msg),this);
#else 
	/*设置设备参数并得到返回值*/
	int st  = set_device_info(&msg);
	
	if(st == SPK_ERR_NONE)
	{
		get_device_info(&msg);
		send_packet(CMD_DEVICE_CTRL_ACK,&msg,sizeof(msg),this);
	}
	else
	{
		/*设置结果发送到PC*/
		send_packet(CMD_DEVICE_CTRL_ACK,&st,4,this);
	}
	return st;
#endif 
}

#pragma warning(pop)


